package pe.gob.foncodes.ssa.ws.impl;

import java.net.InetAddress;
import java.net.UnknownHostException;
import pe.gob.foncodes.ssa.bs.common.util.ServiceException;
import pe.gob.foncodes.ssa.ws.*;
import pe.gob.foncodes.ssa.ws.bean.ObtenerParametrosResult;
import pe.gob.foncodes.ssa.ws.bean.PreguntaSecreta;
import pe.gob.foncodes.ssa.ws.bean.ListarPregSecretaResult;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.jws.WebService;
import org.apache.log4j.Logger;
import pe.gob.foncodes.ssa.bs.common.util.Constante;
import pe.gob.foncodes.ssa.bs.common.util.DateHelper;
import pe.gob.foncodes.ssa.bs.common.util.PasswordHelper;
import pe.gob.foncodes.ssa.bs.seguridad.domain.General;
import pe.gob.foncodes.ssa.bs.seguridad.domain.SeguridadAdicional;
import pe.gob.foncodes.ssa.bs.seguridad.domain.SeguridadAdicionalPK;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Usuario;
import pe.gob.foncodes.ssa.web.util.Utilitarios;
import pe.gob.foncodes.ssa.ws.bean.ActualizaPregSecretaResult;
import pe.gob.foncodes.ssa.ws.bean.CambiarContraseniaResult;
import pe.gob.foncodes.ssa.ws.bean.ConfirmarIdentidadResult;
import pe.gob.foncodes.ssa.ws.bean.ContactarAdministradorResult;
import pe.gob.foncodes.ssa.ws.bean.DatosOlvidoContrasenia;
import pe.gob.foncodes.ssa.ws.bean.DatosUsuario;
import pe.gob.foncodes.ssa.ws.bean.OlvidoContraseniaResult;
import pe.gob.foncodes.ssa.ws.bean.AutenticarUsuarioResult;
import pe.gob.foncodes.ssa.ws.bean.AutorizarUsuarioResult;
import pe.gob.foncodes.ssa.ws.bean.OpcionMenu;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import pe.gob.foncodes.ssa.bs.common.service.GenericService;
import pe.gob.foncodes.ssa.bs.common.util.StringHelper;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Accion;
import pe.gob.foncodes.ssa.bs.seguridad.domain.ControlAcceso;
import pe.gob.foncodes.ssa.bs.seguridad.domain.HorarioPerfil;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Modulo;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Personal;
import pe.gob.foncodes.ssa.bs.seguridad.domain.UsuarioPerfil;
import pe.gob.foncodes.ssa.bs.seguridad.domain.UsuarioSegumiento;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Zonal;
import pe.gob.foncodes.ssa.ws.bean.AccionMenu;
import pe.gob.foncodes.ssa.ws.bean.CerrarSesionResult;
import pe.gob.foncodes.ssa.ws.bean.ParametroGeneral;
import pe.gob.foncodes.ssa.ws.bean.UnidadTerritorial;

@WebService(serviceName = "SistemaSeguridadWS",
targetNamespace = "http://ws.ssa.foncodes.gob.pe/",
endpointInterface = "pe.gob.foncodes.ssa.ws.SistemaSeguridadWS")
public class SistemaSeguridadWSImpl implements SistemaSeguridadWS {

    protected static Logger log = Logger.getLogger(SistemaSeguridadWSImpl.class);
    private Date logDate = DateHelper.getFechaActual();
    private DecimalFormat formatoDecimal = new DecimalFormat("####.#");
    private GenericService service;
    private static final Pattern SUB_ERROR_CODE = Pattern.compile(".*\\s([0-9a-f]{3,4}).*");
    private Integer intentoFallido = 0;
    private String textoCaptchaGuardada = "";
    private Date fechaUltIngresoExitoso;
    private Date ultimoIngreso;
    SimpleDateFormat formatoFecha = new SimpleDateFormat("dd/MM/yyyy HH:mm");
    private int intentosValidos = 0;
    private int intentosRechazados = 0;
    
    public SistemaSeguridadWSImpl() {
    }

    @Override
    public AutenticarUsuarioResult AutenticarUsuario(String codigoUsuario,
            String password, String nidModulo) throws Exception {

        AutenticarUsuarioResult result = new AutenticarUsuarioResult();
        DatosUsuario datosUsuario = new DatosUsuario();
        UnidadTerritorial unidadTerritorial[] = null;
        GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
        gcal.setTime(new Date());
        Date fechaActual = gcal.getTime();
        intentosValidos = 0;
        intentosRechazados = 0;
        boolean registraAcesso = false;
        if (codigoUsuario == null || codigoUsuario.trim().equals("")) {
            result.setCodError(1);
            result.setMensaje("Por favor ingresa tu código de usuario");
        } else {
            if (password == null || password.trim().equals("")) {
                result.setCodError(2);
                result.setMensaje("Por favor ingresa tu contraseña");
            }else if(nidModulo == null || nidModulo.trim().equals("")){
                result.setCodError(16);
                result.setMensaje("Por favor ingresa el nidModulo");
            } else {
                if(Utilitarios.tieneLetras(nidModulo)){
                    result.setCodError(4);
                    result.setMensaje("Módulo no existe");
                }else{
                    if (codigoUsuario.trim().charAt(0) == Constante.CARACTER_USUARIO_DOMINIO) {
                        Long maximoNroIntentosLogin = Long.valueOf(((General) getService().findByNamedQueryUniqueRow("General.findTxtParametroEstado", new Object[]{Constante.MAXIMO_NRO_INTENTOS_LOGIN, Constante.ESTADO_ACTIVO})).getTxtValor());
                        int minimoNroIntentosLogin = maximoNroIntentosLogin.intValue() - 2;
                        int minimoMasUnoNroIntentosLogin = maximoNroIntentosLogin.intValue() - 1;

                        List<Usuario> lstUser = null;
                        lstUser = getService().findByNamedQuery("Usuario.findByCodUsuario", new Object[]{codigoUsuario});
                        if (lstUser.isEmpty()) {
                            result.setCodError(3);
                            result.setMensaje("Usuario no existe");
                        } else {
                            List<Modulo> lstModulo = null;
                            lstModulo = getService().findByNamedQuery("Modulo.findByNidModuloFlgActivo", new Object[]{Long.parseLong(nidModulo), Constante.ESTADO_ACTIVO});
                            if (lstModulo.isEmpty()) {
                                result.setCodError(4);
                                result.setMensaje("Módulo no existe");
                            } else {
                                Usuario user = lstUser.get(0);
                                
                                //datos del usuario
                                datosUsuario.setCodigoUsuario(user.getCodUsuario());
                                datosUsuario.setNidUsuario(user.getId());
                                datosUsuario.setNombreUsuario(user.getNombreCompleto());
                                datosUsuario.setTipoUsuario(user.getTipUsuario());
                                if(user.getTxtCorreoElectronico1() != null){
                                    datosUsuario.setTxtCorreoElectronico1(user.getTxtCorreoElectronico1());
                                }
                                Modulo module = lstModulo.get(0);
                                List<Zonal> lstZonal = getService().findByNamedQuery("Zonal.findByNidUsuarioNidModuloActivos", new Object[]{user.getId(), module.getId()});
                                if (lstZonal.isEmpty()) {
                                    result.setCodError(5);
                                    result.setMensaje("Usuario no tiene permisos para acceder al Módulo");
                                } else {
                                    if (codigoUsuario != null) {
                                        codigoUsuario = codigoUsuario.toUpperCase().trim();
                                        String enc_clave = password;
                                        enc_clave = retornaClaveEncriptada(enc_clave, codigoUsuario);
                                        user.setTxtClaveEncriptada(enc_clave);
                                    }
                                    //CALCULO DE INTENTOS FALLIDOS
                                    calcularIntentosFallidos(user.getId());
                                    intentoFallido = intentosRechazados;
                                    System.out.println("intentosValidos="+intentosValidos);
                                    System.out.println("intentosRechazados="+intentosRechazados);
                                    System.out.println("fechaUltIngresoExitoso="+formatoFecha.format(fechaUltIngresoExitoso));
                                    System.out.println("ultimoIngreso="+formatoFecha.format(ultimoIngreso));
        
                                    ControlAcceso loginLog = new ControlAcceso();
                                    loginLog.setNidUsuario(user);
                                    loginLog.setCodZonal(user.getCodZonal());
                                    loginLog.setTxtSessionid(null);
                                    loginLog.setNidModulo(module);
                                    loginLog.setTipOperacion(Constante.TIPO_OPERACION_INICIO_SESION);

                                    /*if (intentoFallido >= minimoNroIntentosLogin && textoCaptcha != null && !textoCaptcha.trim().equals("")) {
                                        if (!textoCaptcha.equals(textoCaptchaGuardada)) {
                                            result.setCodError(6);
                                            result.setMensaje("Los caracteres no coincideron con la imagen. Vuelva a intentarlo");
                                            return result;
                                        }
                                    }*/
                                    if (StringHelper.miCad(user.getTxtClave(), ",").equals(user.getTxtClaveEncriptada())) {
                                        if (user.getFlgActivo().equals(Constante.ESTADO_INACTIVO)) {
                                            result.setCodError(17);
                                            result.setMensaje("Usuario no se encuentra activo");
                                            return result;
                                        } else if (user.getFlgBloqueado().equals(Constante.ESTADO_BLOQUEADO)) {
                                            result.setCodError(7);
                                            result.setMensaje("Usuario bloqueado");
                                            result.setDatosUsuario(datosUsuario);
                                            return result;
                                        } else if (user.getFlgCambioClave().equals(Constante.CAMBIO_DE_CLAVE)) {
                                            result.setCodError(8);
                                            result.setMensaje("Contraseña Temporal, debe de cambiarla");
                                            result.setDatosUsuario(datosUsuario);
                                            return result;
                                        } else if (validaCaducidadClave(user.getFlgCaducidadClave(), gcal.getTime(), user.getFecCambioClave())) {
                                            result.setCodError(9);
                                            result.setMensaje("La contraseña ha caducado");
                                            return result;
                                        } else {
                                            List<UsuarioPerfil> usuarioPerfilList = getService().findByNamedQuery("UsuarioPerfil.findByNidUsuarioAndFlgActivo", new Object[]{user.getId(), Constante.ESTADO_ACTIVO});
                                            /**
                                             * Validación de caducidad del perfil
                                             */
                                            if (validaCaducidaDelPerfil(usuarioPerfilList, gcal.getTime(), module)) {
                                                result.setCodError(18);
                                                result.setMensaje("El Perfil del Usuario ha caducado, contactese con el administrar del sistema");
                                                return result;
                                            }
                                            if (validaHorarioPerfil(usuarioPerfilList, gcal.getTime())) {
                                                result.setCodError(19);
                                                result.setMensaje("El usuario no se encuentra dentro del horario de acceso permitido");
                                                return result;
                                            }else{
                                                loginLog.setFecRegistro(fechaActual);
                                                loginLog.setFlgAcceso(Constante.INTENTO_VALIDO);
                                                loginLog = (ControlAcceso) getService().save(loginLog);
                                                unidadTerritorial = new UnidadTerritorial[lstZonal.size()];
                                                for (int i = 0; i < lstZonal.size(); i++) {
                                                    unidadTerritorial[i] = new UnidadTerritorial();
                                                    unidadTerritorial[i].setCodZonal(lstZonal.get(i).getCodZonal());
                                                    unidadTerritorial[i].setTxtUnidadTerritorial(lstZonal.get(i).getTxtZonal());
                                                }
                                                //datos del usuario
                                                datosUsuario.setnIdControlAccesoWeb(loginLog.getId());
                                                datosUsuario.setUnidadTerritorial(unidadTerritorial);
                                                //resultado
                                                result.setCodError(0);
                                                result.setMensaje("Usuario autenticado satisfactoriamente");
                                                result.setDatosUsuario(datosUsuario);
                                                intentoFallido = 0;
                                            }
                                        }
                                    } else {
                                        intentoFallido++;
                                        registraAcesso = true;
                                        if (intentoFallido < minimoNroIntentosLogin) {
                                            result.setCodError(10);
                                            result.setMensaje("Su contraseña es incorrecta");
                                            
                                        } else if (intentoFallido < maximoNroIntentosLogin) {
                                            //generando el texto para el captcha
                                            textoCaptchaGuardada = generarTextoCaptcha();
                                            if (intentoFallido == minimoNroIntentosLogin) {
                                                result.setCodError(11);
                                                result.setMensaje("Tiene " + intentoFallido + " intentos fallidos. Recuerde luego del 5to intento su cuenta se bloqueará");
                                            }
                                            if (intentoFallido == minimoMasUnoNroIntentosLogin) {
                                                result.setCodError(12);
                                                result.setMensaje("Tiene " + intentoFallido + " intentos fallidos. Recuerde que luego de este último intento su cuenta se bloqueará");
                                            }
                                        } else {
                                            Usuario usrBloqueo = user;
                                            usrBloqueo.setFecBloqueo(fechaActual);
                                            usrBloqueo.setFlgBloqueado(Constante.ESTADO_BLOQUEADO);
                                            usrBloqueo.setTxtMotivoBloqueo(Constante.MOTIVO_BLOQUEO);
                                            getService().save(usrBloqueo);
                                            
                                            result.setCodError(13);
                                            result.setMensaje("Su cuenta ha sido bloqueada por exceder el número de intentos válidos.");
                                            intentoFallido = 0;
                                        }
                                    }
                                    if (registraAcesso) {
                                        loginLog.setFecRegistro(fechaActual);
                                        loginLog.setFlgAcceso(Constante.INTENTO_RECHAZADO);
                                        //el texto de captcha generado si lo hubiere
                                        if (textoCaptchaGuardada != null && textoCaptchaGuardada.trim().equals("")) {
                                            loginLog.setTxtReferencia(textoCaptchaGuardada);
                                        }
                                        getService().save(loginLog);
                                    }
                                }
                            }
                        }
                    } else {
                        codigoUsuario = codigoUsuario.toUpperCase().trim();
                        LdapContext ctx = null;
                        Hashtable<String, String> env = new Hashtable<String, String>();
                        try {
                            env.put(Context.SECURITY_AUTHENTICATION, "simple");
                            env.put(Context.SECURITY_PRINCIPAL, codigoUsuario + Constante.CARACTER_USUARIO_DOMINIO + Constante.DOMAIN_CONTROLLER);
                            env.put(Context.SECURITY_CREDENTIALS, password);
                            env.put(Context.INITIAL_CONTEXT_FACTORY, Constante.INITIAL_CONTEXT_FACTORY);
                            env.put(Context.PROVIDER_URL, Constante.LDAP_SERVER);
                            env.put("java.naming.ldap.attributes.binary", "objectSID");
                            ctx = new InitialLdapContext(env, null);
                            ctx.reconnect(null);

                            result = loginUsuarioDominio(codigoUsuario, Long.parseLong(nidModulo));
                        } catch (AuthenticationException a) {
                            result.setCodError(14);
                            log.error("Authentication failed: " + a);
                            int subErrorCode = parseSubErrorCode(a.getMessage());
                            switch (subErrorCode) {
                                case 1331:
                                    result.setMensaje("Usuario Inactivo");
                                    break;
                                case 1793:
                                    result.setMensaje("La Contraseña Expiro");
                                    break;
                                case 1907:
                                    result.setMensaje("La contraseña debe cambiarla por primera vez");
                                    break;
                                case 1326:
                                    result.setMensaje("Verifique su código de usuario y contraseña de red");
                                    break;
                                default:
                                    result.setMensaje("Ha ocurrido un error con su cuenta. Comuniquese con el administrador");
                                    log.info("Error " + subErrorCode);
                                    break;
                            }
                        } catch (NamingException e) {
                            log.error("Failed to bind to LDAP / get account information: " + e);
                            result.setCodError(15);
                            result.setMensaje("Ha ocurrido un error con su cuenta. Comuniquese con el administrador");
                        } finally {
                            if (ctx != null) {
                                ctx.close();
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    @Override
    public CambiarContraseniaResult CambiarContrasenia(long nidUsuario, String contraseniaAnterior,
            String contraseniaNueva, String verificaContraseniaNueva) {

        CambiarContraseniaResult cambioResult = new CambiarContraseniaResult();
        try {
            List<Usuario> lstUsuario = getService().findByNamedQuery("Usuario.findById", new Object[]{nidUsuario});
            if (lstUsuario.isEmpty()) {
                cambioResult.setCodError(1);
                cambioResult.setMensaje("El usuario no es válido");
            } else {
                Usuario oUsuario = lstUsuario.get(0);
                if(oUsuario.getTipUsuario().equals(Constante.USUARIO_TIPO_INTERNO)){
                    cambioResult.setCodError(8);
                    cambioResult.setMensaje("El usuario es de tipo INTERNO");
                }else{
                    String claveSinEncriptar = contraseniaNueva;
                    if (validatePass(contraseniaNueva, verificaContraseniaNueva, cambioResult)) {
                        double tiempoEsperaCambioPass = 0;
                        int maximoPassAlamcenados = 0;
                        int maximoPassGuardados = 0;
                        General genTiempoEspera = null;
                        General genPassAlamcenados = null;
                        General genPassGuardados = null;
                        List<General> lstGeneral = getService().findByNamedQuery("General.findTxtParametroEstado", new Object[]{Constante.TIEMPO_ESPERA_CAMBIO_PASS_DIAS, Constante.ESTADO_ACTIVO});
                        if (lstGeneral.isEmpty()) {
                            log.error(String.format("Método %s : %s", "CambiarContrasenia", "No se ha definido el Parametro " + Constante.TIEMPO_ESPERA_CAMBIO_PASS_DIAS));
                            cambioResult.setCodError(2);
                            cambioResult.setMensaje("No se pudo determinar el Tiempo de Espera para el cambio de contraseña");
                            return cambioResult;
                        } else {
                            genTiempoEspera = lstGeneral.get(0);
                            if(genTiempoEspera.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                                tiempoEsperaCambioPass = Double.valueOf(lstGeneral.get(0).getTxtValor());
                            }
                        }
                        lstGeneral = null;
                        lstGeneral = getService().findByNamedQuery("General.findTxtParametroEstado", new Object[]{Constante.MAXIMOS_PASSWORDS_ALMACENADOS, Constante.ESTADO_ACTIVO});
                        if (!lstGeneral.isEmpty()) {
                            genPassAlamcenados = lstGeneral.get(0);
                            if(genPassAlamcenados.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                                maximoPassAlamcenados = Integer.valueOf(genPassAlamcenados.getTxtValor());
                            }
                        }
                        lstGeneral = null;
                        lstGeneral = getService().findByNamedQuery("General.findTxtParametroEstado", new Object[]{Constante.MAXIMOS_PASSWORDS_REPETIDOS, Constante.ESTADO_ACTIVO});
                        if (!lstGeneral.isEmpty()) {
                            genPassGuardados = lstGeneral.get(0);
                            if(genPassGuardados.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                                maximoPassGuardados = Integer.valueOf(genPassGuardados.getTxtValor());
                            }
                        }
                        //Verifico Fecha del ultimo cambio de contrasenia
                        if (tiempoEsperaCambioPass != 0 && DateHelper.fechasDiferenciaEnDias(logDate, oUsuario.getFecCambioClave()) <= tiempoEsperaCambioPass) {
                            cambioResult.setCodError(3);
                            cambioResult.setMensaje("Debe esperar un plazo mínimo de " + formatoDecimal.format(tiempoEsperaCambioPass * 24) + " hora(s) para poder cambiar su contraseña.");
                        } else {
                            String claveTempAnterior = retornaClaveEncriptada(contraseniaAnterior, oUsuario.getCodUsuario());
                            if (!StringHelper.miCad(oUsuario.getTxtClave(), ",").equals(claveTempAnterior)) {
                                cambioResult.setCodError(9);
                                cambioResult.setMensaje("Los valores de Contraseña anterior y su contraseña actual son diferentes. Por favor, asegúrese que sean iguales.");
                            }else{
                                if (contraseniaNueva.equals(verificaContraseniaNueva)) {
                                    String claveFinal = retornaClaveEncriptada(contraseniaNueva, oUsuario.getCodUsuario());
                                    if (PasswordHelper.controlPass(oUsuario.getTxtClave(), contraseniaNueva, oUsuario.getCodUsuario(), claveFinal)) {
                                        //Falta validar la cantidad de veces
                                        List<UsuarioSegumiento> lstSeguimiento = getService().findByNamedQuery("UsuarioSegumiento.findByNidUsuarioAndTxtClaveRepetida", new Object[]{oUsuario.getId(), claveFinal});
                                        if(lstSeguimiento != null){
                                            if(lstSeguimiento.size() > maximoPassGuardados){
                                                cambioResult.setCodError(10);
                                                cambioResult.setMensaje("La contraseña ingresada ha superado el límite de veces permitido ( "+maximoPassGuardados+" ) . Por favor, ingrese otra diferente.");
                                                return cambioResult;
                                            }
                                        }
                                        log.info("Start of Transaction: 'Change Password' at " + DateHelper.getFechaActual());
                                        log.info("User initiating transaction" + oUsuario.getCodUsuario());

                                        if (maximoPassAlamcenados == 0) {
                                            oUsuario.setTxtClave(claveFinal);
                                        } else {
                                            String miPassword = "";
                                            miPassword = claveFinal + Constante.SEPARADOR_CONTRASENIA + oUsuario.getTxtClave();
                                            oUsuario.setTxtClave(PasswordHelper.listaPassword(miPassword, maximoPassAlamcenados));
                                        }
                                        oUsuario.setFecCambioClave(DateHelper.getFechaActual());
                                        oUsuario.setFlgBloqueado(Constante.ESTADO_INACTIVO);
                                        oUsuario.setFlgCaducidadClave(Constante.CLAVE_NO_CADUCADA);
                                        oUsuario.setFlgCambioClave(Constante.ESTADO_INACTIVO);

                                        String strcomentario = "<span>Se remite la actualizaci&oacute;en de la siguiente informaci&oacute;n: </span><br/><br/>"
                                                + "<span>Nueva Contrase&ntilde;a: " + claveSinEncriptar + "</span><br/><br/>";
                                        if (oUsuario.getTxtCorreoElectronico1() != null) {
                                            strcomentario += "<span>Correo Principal: " + oUsuario.getTxtCorreoElectronico1() + "</span><br/>";
                                        }
                                        if (oUsuario.getTxtCorreoElectronico2() != null) {
                                            strcomentario += "<span>Correo Alternativo: " + oUsuario.getTxtCorreoElectronico2() + "</span><br/>";
                                        }
                                        strcomentario += "<br/><span>Se solicita verificar los datos, si hubiera alg&uacute;n error comunicar a el &aacute;rea correspondiente.</span><br/>";
                                        strcomentario += "<br/><br/><span>Nota:  Este es un mensaje informativo enviado de forma autom&aacute;tica.</span><br/>";
                                        strcomentario += "<span>Agradecemos no responder a esta direcci&oacute;n de correo</span><br/>";

                                        try {
                                            getService().save(oUsuario);
                                            log.info("End of Transaction: 'Change Password'");
                                            cambioResult.setCodError(0);
                                            cambioResult.setMensaje("Su contraseña ha sido cambiada satisfactoriamente");
                                            if (oUsuario.getTxtCorreoElectronico1() != null) {
                                                enviaMail(oUsuario.getTxtCorreoElectronico1(), "Notificación del sistema de seguridad de FONCODES - Cambio de Contraseña", strcomentario);
                                            }
                                            if (oUsuario.getTxtCorreoElectronico2() != null) {
                                                enviaMail(oUsuario.getTxtCorreoElectronico2(), "Notificación del sistema de seguridad de FONCODES - Cambio de Contraseña", strcomentario);
                                            }
                                        } catch (Exception e) {
                                            cambioResult.setCodError(4);
                                            cambioResult.setMensaje("No se pudo cambiar la contraseña, ocurrió un error al guardar");

                                            log.error(String.format("Método %s : %s", "CambiarContrasenia", "Se detectó un error al guardar la contraseña : " + e));
                                        }
                                    } else {
                                        cambioResult.setCodError(5);
                                        cambioResult.setMensaje(PasswordHelper.mensaje);
                                    }
                                } else {
                                    cambioResult.setCodError(6);
                                    cambioResult.setMensaje("La nueva contraseña y repita su nueva contraseña son diferentes. Por favor, asegúrese que sean iguales");
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.error(String.format("Método %s : %s", "CambiarContrasenia", ex));
            cambioResult.setCodError(7);
            cambioResult.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return cambioResult;
    }

    @Override
    public CambiarContraseniaResult OlvidoCambiarContrasenia(long nidUsuario, 
            String contraseniaNueva, String verificaContraseniaNueva) {
        CambiarContraseniaResult cambioResult = new CambiarContraseniaResult();
        try {
            List<Usuario> lstUsuario = getService().findByNamedQuery("Usuario.findById", new Object[]{nidUsuario});
            if (lstUsuario.isEmpty()) {
                cambioResult.setCodError(1);
                cambioResult.setMensaje("El usuario no es válido");
            } else {
                Usuario oUsuario = lstUsuario.get(0);
                if(oUsuario.getTipUsuario().equals(Constante.USUARIO_TIPO_INTERNO)){
                    cambioResult.setCodError(8);
                    cambioResult.setMensaje("El usuario es de tipo INTERNO");
                }else{
                    String claveSinEncriptar = contraseniaNueva;
                    if (validatePass(contraseniaNueva, verificaContraseniaNueva, cambioResult)) {
                        double tiempoEsperaCambioPass = 0;
                        int maximoPassAlamcenados = 0;
                        General genTiempoEspera = null;
                        General genPassAlamcenados = null;
                        List<General> lstGeneral = getService().findByNamedQuery("General.findTxtParametroEstado", new Object[]{Constante.TIEMPO_ESPERA_CAMBIO_PASS_DIAS, Constante.ESTADO_ACTIVO});
                        if (lstGeneral.isEmpty()) {
                            log.error(String.format("Método %s : %s", "CambiarContrasenia", "No se ha definido el Parametro " + Constante.TIEMPO_ESPERA_CAMBIO_PASS_DIAS));
                            cambioResult.setCodError(2);
                            cambioResult.setMensaje("No se pudo determinar el Tiempo de Espera para el cambio de contraseña");
                            return cambioResult;
                        } else {
                            genTiempoEspera = lstGeneral.get(0);
                            if(genTiempoEspera.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                                tiempoEsperaCambioPass = Double.valueOf(lstGeneral.get(0).getTxtValor());
                            }
                        }
                        lstGeneral = null;

                        lstGeneral = getService().findByNamedQuery("General.findTxtParametroEstado", new Object[]{Constante.MAXIMOS_PASSWORDS_ALMACENADOS, Constante.ESTADO_ACTIVO});
                        if (!lstGeneral.isEmpty()) {
                            genPassAlamcenados = lstGeneral.get(0);
                            if(genPassAlamcenados.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                                maximoPassAlamcenados = Integer.valueOf(genPassAlamcenados.getTxtValor());
                            }
                        }
                        //Verifico Fecha del ultimo cambio de contrasenia
                        if (tiempoEsperaCambioPass != 0 && DateHelper.fechasDiferenciaEnDias(logDate, oUsuario.getFecCambioClave()) <= tiempoEsperaCambioPass) {
                            cambioResult.setCodError(3);
                            cambioResult.setMensaje("Debe esperar un plazo mínimo de " + formatoDecimal.format(tiempoEsperaCambioPass * 24) + " hora(s) para poder cambiar su contraseña.");
                        } else {
                            if (contraseniaNueva.equals(verificaContraseniaNueva)) {
                                String claveFinal = retornaClaveEncriptada(contraseniaNueva, oUsuario.getCodUsuario());
                                if (PasswordHelper.controlPass(oUsuario.getTxtClave(), contraseniaNueva, oUsuario.getCodUsuario(), claveFinal)) {
                                    log.info("Start of Transaction: 'Change Password' at " + DateHelper.getFechaActual());
                                    log.info("User initiating transaction" + oUsuario.getCodUsuario());

                                    if (maximoPassAlamcenados == 0) {
                                        oUsuario.setTxtClave(claveFinal);
                                    } else {
                                        String miPassword = "";
                                        miPassword = claveFinal + Constante.SEPARADOR_CONTRASENIA + oUsuario.getTxtClave();
                                        oUsuario.setTxtClave(PasswordHelper.listaPassword(miPassword, maximoPassAlamcenados));
                                    }
                                    oUsuario.setFecCambioClave(DateHelper.getFechaActual());
                                    oUsuario.setFlgBloqueado(Constante.ESTADO_INACTIVO);
                                    oUsuario.setFlgCaducidadClave(Constante.CLAVE_NO_CADUCADA);
                                    oUsuario.setFlgCambioClave(Constante.ESTADO_INACTIVO);

                                    String strcomentario = "<span>Se remite la actualizaci&oacute;en de la siguiente informaci&oacute;n: </span><br/><br/>"
                                            + "<span>Nueva Contrase&ntilde;a: " + claveSinEncriptar + "</span><br/><br/>";
                                    if (oUsuario.getTxtCorreoElectronico1() != null) {
                                        strcomentario += "<span>Correo Principal: " + oUsuario.getTxtCorreoElectronico1() + "</span><br/>";
                                    }
                                    if (oUsuario.getTxtCorreoElectronico2() != null) {
                                        strcomentario += "<span>Correo Alternativo: " + oUsuario.getTxtCorreoElectronico2() + "</span><br/>";
                                    }
                                    strcomentario += "<br/><span>Se solicita verificar los datos, si hubiera alg&uacute;n error comunicar a el &aacute;rea correspondiente.</span><br/>";
                                    strcomentario += "<br/><br/><span>Nota:  Este es un mensaje informativo enviado de forma autom&aacute;tica.</span><br/>";
                                    strcomentario += "<span>Agradecemos no responder a esta direcci&oacute;n de correo</span><br/>";

                                    try {
                                        getService().save(oUsuario);
                                        log.info("End of Transaction: 'Change Password'");
                                        cambioResult.setCodError(0);
                                        cambioResult.setMensaje("Su contraseña ha sido cambiada satisfactoriamente");
                                        if (oUsuario.getTxtCorreoElectronico1() != null) {
                                            enviaMail(oUsuario.getTxtCorreoElectronico1(), "Notificación del sistema de seguridad de FONCODES - Cambio de Contraseña", strcomentario);
                                        }
                                        if (oUsuario.getTxtCorreoElectronico2() != null) {
                                            enviaMail(oUsuario.getTxtCorreoElectronico2(), "Notificación del sistema de seguridad de FONCODES - Cambio de Contraseña", strcomentario);
                                        }
                                    } catch (Exception e) {
                                        cambioResult.setCodError(4);
                                        cambioResult.setMensaje("No se pudo cambiar la contraseña, ocurrió un error al guardar");

                                        log.error(String.format("Método %s : %s", "CambiarContrasenia", "Se detectó un error al guardar la contraseña : " + e));
                                    }
                                } else {
                                    cambioResult.setCodError(5);
                                    cambioResult.setMensaje(PasswordHelper.mensaje);
                                }
                            } else {
                                cambioResult.setCodError(6);
                                cambioResult.setMensaje("La nueva contraseña y repita su nueva contraseña son diferentes. Por favor, asegúrese que sean iguales");
                            }

                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.error(String.format("Método %s : %s", "CambiarContrasenia", ex));
            cambioResult.setCodError(7);
            cambioResult.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return cambioResult;
    }
    
    @Override
    public ListarPregSecretaResult ListarPreguntaSecreta() {
        ListarPregSecretaResult result = new ListarPregSecretaResult();
        try {
            List<General> lstGeneral = getService().findByNamedQuery("General.findByTxtDominioEstado", new Object[]{Constante.DOMINIO_PREGUNTA_SECRETA, Constante.ESTADO_ACTIVO});
            if (lstGeneral.isEmpty()) {
                result.setCodError(1);
                result.setMensaje("No existen preguntas secretas registradas");
            } else {
                PreguntaSecreta[] preguntaSecreta = new PreguntaSecreta[lstGeneral.size()];
                for (int i = 0; i < lstGeneral.size(); i++) {
                    preguntaSecreta[i] = new PreguntaSecreta();
                    preguntaSecreta[i].setIdPreguntaSecreta(lstGeneral.get(i).getId());
                    preguntaSecreta[i].setDescripcionPreguntaSecreta(lstGeneral.get(i).getTxtParametro());
                }

                result.setCodError(0);
                result.setMensaje("Se devolvió el listado de las preguntas secretas satisfactoriamente");
                result.setPreguntaSecreta(preguntaSecreta);
            }
        } catch (Exception e) {
            log.error(String.format("Método %s : %s", "ListarPreguntaSecreta", e));
            result.setCodError(2);
            result.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return result;
    }

    @Override
    public ActualizaPregSecretaResult ActualizarPreguntaSecreta(Long nidUsuario,
            Long nidPreguntaSecreta, String respuestaPreguntaSecreta) {

        ActualizaPregSecretaResult result = new ActualizaPregSecretaResult();

        if (nidUsuario == null) {
            result.setCodError(1);
            result.setMensaje("El id del usuario no es válido");
        } else if (nidPreguntaSecreta == null) {
            result.setCodError(2);
            result.setMensaje("El id de la pregunta secreta no es válido");
        } else if (respuestaPreguntaSecreta == null || respuestaPreguntaSecreta.trim().equals("")) {
            result.setCodError(3);
            result.setMensaje("La respuesta a la pregunta secreta no es válida");
        } else {
            try {
                List<Usuario> lstUser = getService().findByNamedQuery("Usuario.findById", new Object[]{nidUsuario});
                Usuario miUsr=null;
                if (lstUser.isEmpty()) {
                    result.setCodError(5);
                    result.setMensaje("Usuario no registrado");
                } else {
                    miUsr = lstUser.get(0);
                    List<General> lstGeneral = getService().findByNamedQuery("General.findByIdTxtDominio", new Object[]{nidPreguntaSecreta, Constante.DOMINIO_PREGUNTA_SECRETA});
                    General gen = null;
                    if (lstGeneral.isEmpty()) {
                        result.setCodError(6);
                        result.setMensaje("El Id de la Pregunta Secreta no existe");
                    } else {
                        gen = lstGeneral.get(0);
                        //obteniendo la seguridad adicional activa del usuario para darlas de baja y crear la nueva
                        List<SeguridadAdicional> lstSegAdicional = getService().findByNamedQuery("SeguridadAdicional.findByNIdUsuarioAndEstado", new Object[]{nidUsuario, Constante.ESTADO_ACTIVO});
                        for (SeguridadAdicional oSegAdicional : lstSegAdicional) {
                            oSegAdicional.setFlgActivo(Constante.ESTADO_INACTIVO);
                            getService().save(oSegAdicional);
                        }
                        
                        //creando un nuevo registro de seguridad adicional
                        SeguridadAdicional oNewSegAdicional = new SeguridadAdicional();
                        SeguridadAdicionalPK oSegAdicionalPK = new SeguridadAdicionalPK(nidUsuario, nidPreguntaSecreta);
                        oNewSegAdicional.setSeguridadAdicionalPK(oSegAdicionalPK);
                        oNewSegAdicional.setFlgActivo(Constante.ESTADO_ACTIVO);
                        oNewSegAdicional.setFecRegistro(logDate);
                        oNewSegAdicional.setTxtRespuesta(respuestaPreguntaSecreta.trim());

                        getService().save(oNewSegAdicional);

                        String strcomentario = "<span>Se remite la actualizaci&oacute;n de la siguiente informaci&oacute;n: </span><br/><br/>"
                                + "<span>Pregunta Secreta: " + gen.getTxtParametro()+"</span><br/>"
                                + "<span>Respuesta Secreta: " + respuestaPreguntaSecreta.trim() +"</span><br/><br/> ";
                        if (miUsr.getTxtCorreoElectronico1() != null) {
                            strcomentario += "<span>Correo Principal: " + miUsr.getTxtCorreoElectronico1()+"</span><br/>";
                        }
                        if (miUsr.getTxtCorreoElectronico2() != null) {
                            strcomentario += "<span>Correo Alternativo: " + miUsr.getTxtCorreoElectronico2()+"</span><br/> ";
                        }
                        strcomentario += "<br/><span>Se solicita verificar los datos, si hubiera alg&uacute;n error comunicar a el &aacute;rea correspondiente.</span><br/>";

                        strcomentario += "<br/><br/><span>Nota:  Este es un mensaje informativo enviado de forma autom&aacute;tica.</span><br/>";
                        strcomentario += "<span>Agradecemos no responder a esta direcci&oacute;n de correo</span><br/>";

                        if (miUsr.getTxtCorreoElectronico1() != null) {
                            enviaMail(miUsr.getTxtCorreoElectronico1(), "Notificación del sistema de seguridad de FONCODES - Actualización de Pregunta Secreta", strcomentario);
                        }
                        if (miUsr.getTxtCorreoElectronico2() != null) {
                            enviaMail(miUsr.getTxtCorreoElectronico2(), "Notificación del sistema de seguridad de FONCODES - Actualización de Pregunta Secreta", strcomentario);
                        }
                        result.setCodError(0);
                        result.setMensaje("Se cambió la pregunta secreta satisfactoriamente");
                    }
                }
            } catch (Exception e) {
                result.setCodError(4);
                result.setMensaje(e.getMessage());
            }
        }

        return result;
    }

    @Override
    public OlvidoContraseniaResult OlvidoContrasenia(String codigoUsuario) {
        OlvidoContraseniaResult result = new OlvidoContraseniaResult();
        DatosOlvidoContrasenia datosOlvidoContrasenia = new DatosOlvidoContrasenia();

        if (codigoUsuario == null || codigoUsuario.trim().equals("")) {
            result.setCodError(1);
            result.setMensaje("Por favor ingresa tu codigo de usuario");
        } else {
            try {
                List<Usuario> lstUser = getService().findByNamedQuery("Usuario.findByCodUsuario", new Object[]{codigoUsuario});
                if (lstUser.isEmpty()) {
                    result.setCodError(2);
                    result.setMensaje("Usuario no registrado");
                } else {
                    Usuario user = lstUser.get(0);
                    user.setTxtClaveEncriptada(user.getTxtClave());
                    System.out.println("inicia seg adicional");
                    List<SeguridadAdicional> lstSegAdicional = getService().findByNamedQuery("SeguridadAdicional.findByNIdUsuarioAndEstado", new Object[]{user.getId(), Constante.ESTADO_ACTIVO});

                    datosOlvidoContrasenia.setNidUsuario(user.getId());
                    datosOlvidoContrasenia.setCodigoUsuario(user.getCodUsuario());
                    if (!lstSegAdicional.isEmpty()) {
                        datosOlvidoContrasenia.setNidPreguntaSecreta(lstSegAdicional.get(0).getGeneral().getId());
                        datosOlvidoContrasenia.setPreguntaSecreta(lstSegAdicional.get(0).getGeneral().getTxtParametro().toUpperCase());

                        result.setCodError(0);
                        result.setMensaje("Se obtuvo los datos del usuario correctamente");
                        result.setDatosOlvidoContrasenia(datosOlvidoContrasenia);
                    } else {
                        result.setCodError(4);
                        result.setMensaje("El usuario no tiene configurado su pregunta secreta");
                    }
                }
            } catch (Exception e) {
                log.error(String.format("Método %s : %s", "OlvidoContrasenia", e));
                result.setCodError(3);
                result.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
            }
        }
        return result;
    }

    @Override
    public ConfirmarIdentidadResult ConfirmarIdentidad(Long nidUsuario,
            Long nidPreguntaSecreta, String nroDocId, String fechaNacimiento,
            String respuestaPreguntaSecreta) throws Exception {
        ConfirmarIdentidadResult result = new ConfirmarIdentidadResult();
        if (nidUsuario == null) {
            result.setCodError(1);
            result.setMensaje("El id del usuario no es válido");
        } else if (nidPreguntaSecreta == null) {
            result.setCodError(2);
            result.setMensaje("El id de la pregunta secreta no es válido");
        } else if (nroDocId == null || nroDocId.trim().equals("")) {
            result.setCodError(3);
            result.setMensaje("El número de documento de identidad no es válido");
        } else if (respuestaPreguntaSecreta == null || respuestaPreguntaSecreta.trim().equals("")) {
            result.setCodError(4);
            result.setMensaje("La respuesta a la pregunta secreta no es válida");
        /*} else if ((fechaNacimiento != null || !fechaNacimiento.trim().equals("")) && !DateHelper.EsFechaValida(fechaNacimiento, "dd/MM/yyyy")) {
            result.setCodError(5);
            result.setMensaje("La fecha de nacimiento no es válida");
         * */
        } else {
            //buscando al usuario por su id
            List<Usuario> lstUser = getService().findByNamedQuery("Usuario.findById", new Object[]{nidUsuario});

            if (lstUser.isEmpty()) {
                result.setCodError(6);
                result.setMensaje("Usuario no registrado");
            } else {
                Usuario oUsuario = lstUser.get(0);
                //Si tiene asociado una persona
                if(oUsuario.getNidPersonal() != null){
                    List<Personal> lstPersonal = getService().findByNamedQuery("Personal.findByNidPersonal", new Object[]{oUsuario.getNidPersonal()});
                    if(!lstPersonal.isEmpty()){
                        oUsuario.setPersonal(lstPersonal.get(0));
                        //Si tiene fecha de nacimiento, se valida
                        if(oUsuario.getPersonal().getFecNacimiento()!=null){
                            if ((fechaNacimiento != null || !fechaNacimiento.trim().equals("")) && !DateHelper.EsFechaValida(fechaNacimiento, "dd/MM/yyyy")) {
                                result.setCodError(5);
                                result.setMensaje("La fecha de nacimiento no es válida");
                                return result;
                            }
                            String sFechaNac = DateHelper.StringToDate(oUsuario.getPersonal().getFecNacimiento(), "dd/MM/yyyy");
                            if(!fechaNacimiento.equals(sFechaNac)){
                                result.setCodError(8);
                                result.setMensaje("La fecha de Nacimiento del Usuario no corresponde");
                                return result;
                            }
                        }
                    }
                }
                
                //buscando la pregunta secreta del usuario
                List<SeguridadAdicional> lstSegAdicional = getService().findByNamedQuery("SeguridadAdicional.findByNidUsuarioNidGeneralActivo", new Object[]{nidUsuario, nidPreguntaSecreta});
                if (lstSegAdicional.isEmpty()) {
                    result.setCodError(7);
                    result.setMensaje("El Id de la Pregunta Secreta no es válida o no está activa");
                } else {
                    //verificando si la respuesta y los datos del usuario coinciden
                    SeguridadAdicional oSegAdicional = lstSegAdicional.get(0);
                    if (!oUsuario.getCodDni().equals(nroDocId)){
                        result.setCodError(3);
                        result.setMensaje("El número de documento de identidad no es válido");
                    }
                    else if(!oSegAdicional.getTxtRespuesta().toUpperCase().equals(respuestaPreguntaSecreta.toUpperCase())) {
                        result.setCodError(4);
                        result.setMensaje("La respuesta a la pregunta secreta no es válida");
                    }else{
                        result.setCodError(0);
                        result.setMensaje("Los datos del Usuario se validaron correctamente");
                    }
                    /*if (oUsuario.getCodDni().equals(nroDocId)
                            && oSegAdicional.getTxtRespuesta().toUpperCase().equals(respuestaPreguntaSecreta.toUpperCase())) {
                    } else {
                        result.setCodError(8);
                        result.setMensaje("Los datos del Usuario no corresponden");
                    }*/
                }
            }
        }
        return result;
    }

    @Override
    public ContactarAdministradorResult ContactarAdministrador(String codigoUsuario, String motivoContacto) {
        ContactarAdministradorResult result = new ContactarAdministradorResult();
        if (codigoUsuario == null || codigoUsuario.trim().equals("")) {
            result.setCodError(1);
            result.setMensaje("El código de usuario no es válido");
        } else {
            try {
                List<Usuario> lstUser = getService().findByNamedQuery("Usuario.findByCodUsuario", new Object[]{codigoUsuario});
                if (lstUser.isEmpty()) {
                    result.setCodError(2);
                    result.setMensaje("Usuario no registrado");
                } else {
                    Usuario user = lstUser.get(0);
                    //verificando si el usuario esta activo o no
                    if (!user.getFlgActivo().equals(Constante.ESTADO_ACTIVO)) {
                        result.setCodError(3);
                        result.setMensaje("El Usuario no es válido o está de baja");
                    } else {
                        int numAleatorio = (int) (Math.random() * (999 - 100 + 1) + 100);
                        String firsLetterApeMat = user.getTxtApellidoMaterno().charAt(0)+"";
                        String firsLetterApePat = user.getTxtApellidoPaterno().charAt(0)+"";
                        String firsLetterNombre = user.getTxtNombres().charAt(0)+"";
                        String strcomentario = "<span>Se remite el  c&oacute;digo de usuario  y su contrase&ntilde;a temporal.</span><br/>"
                                + "<span>La  primera vez que ingrese con esta cuenta, el sistema le pedir&aacute; de manera obligatoria el cambio de la contrase&ntilde;a temporal a su nueva clave.</span><br/><br/>"
                                + "<span>C&oacute;digo de Usuario: " + user.getCodUsuario() + "</span><br/>"
                                + "<span>Contrase&ntilde;a Temporal: " + retornaPasswordTemporal(user.getCodUsuario(),firsLetterApeMat,firsLetterApePat,firsLetterNombre, "0", numAleatorio) + "</span><br/>";
                        if (user.getTxtCorreoElectronico1() != null) {
                            strcomentario += "<span>Correo Principal: " + user.getTxtCorreoElectronico1() + "</span><br/>";
                        }
                        if (user.getTxtCorreoElectronico2() != null) {
                            strcomentario += "<span>Correo Alternativo: " + user.getTxtCorreoElectronico2() + "</span><br/>";
                        }
                        strcomentario += "<br/><span>Se solicita verificar los datos, si hubiera alg&uacute;n error comunicar a el &aacute;rea correspondiente.</span><br/>";
                        strcomentario += "<br/><br/><span>Nota:  Este es un mensaje informativo enviado de forma autom&aacute;tica.</span><br/>";
                        strcomentario += "<span>Agradecemos no responder a esta direcci&oacute;n de correo</span><br/>";
                        
                        if (user.getTxtCorreoElectronico1() != null) {
                            enviaMail(user.getTxtCorreoElectronico1(), "Notificación del sistema de seguridad de FONCODES - Contraseña Temporal", strcomentario);
                        }
                        if (user.getTxtCorreoElectronico2() != null) {
                            enviaMail(user.getTxtCorreoElectronico2(), "Notificación del sistema de seguridad de FONCODES - Contraseña Temporal", strcomentario);
                        }
                        log.info("Se mando el email correctamente");

                        user.setFlgCambioClave(Constante.ESTADO_ACTIVO);
                        user.setTxtClave(retornaPasswordTemporal(user.getCodUsuario(), firsLetterApeMat,firsLetterApePat,firsLetterNombre, "1", numAleatorio));

                        getService().save(user);

                        result.setCodError(0);
                        //result.setDatosContactarAdministrador(datosContactarAdministrador);
                        result.setMensaje("Su mensaje ha sido enviado al Administrador. En unos minutos "
                                + "recibirá su contraseña temporal, la que sera enviada a "
                                + "el(los) correo(s) registrado(s) en nuestra base de datos");
                    }
                }
            } catch (Exception e) {
                result.setCodError(4);
                result.setMensaje(e.getMessage());
            }
        }
        return result;
    }

    @Override
    public AutorizarUsuarioResult AutorizarUsuario(long nidUsuario, String nidModulo, String codZonal) {
        AutorizarUsuarioResult result = new AutorizarUsuarioResult();
        try {
            if(nidModulo == null || nidModulo.trim().equals("")){
                result.setCodError(2);
                result.setMensaje("Por favor ingresa el nidModulo");
                return result;
            }
            if (Utilitarios.tieneLetras(nidModulo)) {
                result.setCodError(3);
                result.setMensaje("Módulo no existe");
                return result;
            }
            if (!Utilitarios.tieneNumeros(nidModulo)) {
                result.setCodError(3);
                result.setMensaje("Módulo no existe");
                return result;
            }
            HashMap<OpcionMenu, ArrayList<OpcionMenu>> menuBar = new HashMap<OpcionMenu, ArrayList<OpcionMenu>>();
            List<OpcionMenu> listaOpciones = new ArrayList<OpcionMenu>();
            
            List<Long> lstModulos = getService().getModulosHijos(Long.parseLong(nidModulo));
            OpcionMenu opcionMenu = null;
            List<Object[]> firstLevelNodes = null;
            if(!lstModulos.isEmpty()){
                firstLevelNodes = getService().findByNamedQuery("Opcion.findFirstLevelNodes", new Object[]{nidUsuario, lstModulos, codZonal});
            }else{
                firstLevelNodes = new ArrayList<Object[]>();
            }
            Map<Long, OpcionMenu> mapa= new HashMap<Long, OpcionMenu>();
            for (Object[] obj : firstLevelNodes) {
                opcionMenu = new OpcionMenu();
                opcionMenu.setNidModulo(Long.parseLong(obj[0].toString()));
                opcionMenu.setTxtModulo(obj[1].toString());
                if(obj[2] != null){
                    opcionMenu.setNidModuloPadre(Long.parseLong(obj[2].toString()));
                }
                if(obj[3] != null){
                    opcionMenu.setTxtModuloPadre(obj[3].toString());
                }
                opcionMenu.setNidOpcion(Long.parseLong(obj[4].toString()));
                opcionMenu.setTxtOpcion(obj[5].toString());
                if(obj[6] != null){
                    opcionMenu.setNidOpcionPadre(Long.parseLong(obj[6].toString()));
                }
                opcionMenu.setNumOrden(Integer.parseInt(obj[7].toString()));
                opcionMenu.setNidAccion(Long.parseLong(obj[8].toString()));
                opcionMenu.setTxtAccion(obj[9].toString());
                opcionMenu.setTxtNombreObjeto(obj[10].toString());
                if(obj[11] != null){
                    opcionMenu.setTxtUrl(obj[11].toString());
                }
                opcionMenu.setFlgDefault(obj[12].toString());
                opcionMenu.setFlgConsulta(obj[13].toString());
                if(obj[14] != null){
                    opcionMenu.setTxtOpcionNombreObjeto(obj[14].toString());
                }
                if(obj[15] != null){
                    opcionMenu.setFlgVisible(obj[15].toString());
                }
                if(obj[16] != null){
                    opcionMenu.setFlgPerfilConsulta(obj[16].toString());
                }
                if(mapa.containsKey(opcionMenu.getNidOpcion())){
                    if(mapa.get(opcionMenu.getNidOpcion()).getFlgConsulta().equals(Constante.FLAG_CONSULTA) && !opcionMenu.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                        mapa.put(opcionMenu.getNidOpcion(), opcionMenu);
                    }
                }else{
                    mapa.put(opcionMenu.getNidOpcion(), opcionMenu);
                }
                //listaOpciones.add(opcionMenu);
            }
            listaOpciones.addAll(mapa.values());
            String flgConsultaPadre = "";
            for (OpcionMenu opcion : listaOpciones) {
                if (!menuBar.containsKey(opcion)) {
                    //De tipo acceso total
                    if(opcion.getFlgPerfilConsulta().equals(Constante.FLAG_CONSULTA)){
                        opcion.setFlgConsulta(Constante.FLAG_CONSULTA);
                        flgConsultaPadre = "1";
                    }else{
                        if(opcion.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                            opcion.setFlgConsulta(Constante.FLAG_CONSULTA);
                            flgConsultaPadre = "1";
                        }else{
                            flgConsultaPadre = "0";
                        }
                    }
                    opcion = crearMenuAccion(opcion, nidUsuario, codZonal, flgConsultaPadre);
                    opcion = crearMenuOpcion(opcion, nidUsuario, codZonal, flgConsultaPadre);
                    menuBar.put(opcion, new ArrayList<OpcionMenu>());
                    //crearMenu(opcion, menuBar, nidUsuario, codZonal, flgConsultaPadre);
                }
            }
            result.setCodError(0);
            result.setMensaje("Se autorizó al usuario correctamente");

            //recorriendo el menu construido y armando la respuesta
            if (menuBar.size() > 0) {
                OpcionMenu opcionMenuFinal[] = new OpcionMenu[menuBar.size()];
                int i = 0;
                for (OpcionMenu opcion : ordenaLista(menuBar.keySet())) {
                    opcion.setFlgPerfilConsulta(null);
                    opcionMenuFinal[i] = opcion;
                    i++;
                }
                result.setOpcionMenu(opcionMenuFinal);
            }
        } catch (Exception e) {
            log.error(String.format("Método %s : %s", "AutorizarUsuario", e));
            result.setCodError(1);
            result.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return result;
    }

    public List<OpcionMenu> ordenaLista(Set<OpcionMenu> conjunto){
        List<OpcionMenu> lista = new ArrayList<OpcionMenu>(conjunto);
        Collections.sort(lista, new Comparator<OpcionMenu>(){
            @Override
            public int compare(OpcionMenu o1, OpcionMenu o2) {
                return o1.getNumOrden() - o2.getNumOrden();
            }
        });
        return lista;
    }
    
    public boolean validatePass(String newPassword, String verifyPassword, CambiarContraseniaResult result) {
        boolean success = true;
        if (newPassword == null) {
            newPassword = "";
        }
        if (verifyPassword == null) {
            verifyPassword = "";
        }
        if (newPassword.equals("")) {
            success = false;
            result.setCodError(6);
            result.setMensaje("Debe ingresar correctamente la nueva contraseña.");
        }
        if (!(newPassword.length() > 7)) {
            success = false;
            result.setCodError(10);
            result.setMensaje("La nueva contraseña no puede ser menor a 8 caracteres.");
        }
        if (verifyPassword.equals("") || !(verifyPassword.length() > 7)) {
            success = false;
            result.setCodError(7);
            result.setMensaje("Debe ingresar correctamente la confirmación de la contraseña.");
        }
        if (!(verifyPassword.length() > 7)) {
            success = false;
            result.setCodError(11);
            result.setMensaje("El valor de repita su nueva contraseña no puede ser menor a 8 caracteres.");
        }
        return success;
    }

    private String retornaClaveEncriptada(String txtClave, String codUsuario) throws Exception {
        String enc_clave = "";
        String sql = "SELECT ssa.sf_codificacion('" + txtClave + "','" + codUsuario + "') FROM dual";
        Object obj = getService().createNativeQuery(sql);
        if (obj != null) {
            enc_clave = obj.toString();
        }
        return enc_clave;
    }

    private void enviaMail(String strmailpara, String strsubject, String strcomentario) {
        try {
            String strmail = Utilitarios.getContextUrl("1");
            String struser = Utilitarios.getContextUrl("2");
            String strpass = Utilitarios.getContextUrl("3");
            String strmailde = Utilitarios.getContextUrl("4");

            Properties props = new Properties();
            props.setProperty("mail.smtp.host", strmail);
            //props.setProperty("mail.smtp.starttls.enable", "true");
            props.setProperty("mail.smtp.port", "587");
            props.setProperty("mail.smtp.user", struser);
            props.setProperty("mail.smtp.auth", "false");

            // Preparamos la sesion
            Session session = Session.getDefaultInstance(props);

            // Construimos el mensaje
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(strmailde));
            message.addRecipient(
                    Message.RecipientType.TO,
                    new InternetAddress(strmailpara));

            message.setSubject(strsubject);

            message.setContent(strcomentario, "text/html");
            Transport t = session.getTransport("smtp");
            t.connect(strmail, struser, strpass);
            t.sendMessage(message, message.getAllRecipients());

            // Cierre.
            t.close();
        } catch (Exception e) {
            log.error("ERROR en enviaMail : " + e.getMessage());
        }
    }

    public AutenticarUsuarioResult loginUsuarioDominio(String usuario, long idmodulo) throws Exception {
        AutenticarUsuarioResult result = new AutenticarUsuarioResult();
        DatosUsuario datosUsuario = new DatosUsuario();
        UnidadTerritorial unidadTerritorial[] = null;
        GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
        gcal.setTime(new Date());
        Date fechaActual = gcal.getTime();
        List<Usuario> lstUser = null;
        lstUser = getService().findByNamedQuery("Usuario.findByCodUsuarioFlgActivo", new Object[]{usuario, Constante.ESTADO_ACTIVO});
        if (lstUser.isEmpty()) {
            result.setCodError(3);
            result.setMensaje("Usuario no registrado");
        } else {
            List<Modulo> lstModulo = null;
            lstModulo = getService().findByNamedQuery("Modulo.findByNidModuloFlgActivo", new Object[]{idmodulo, Constante.ESTADO_ACTIVO});
            if (lstModulo.isEmpty()) {
                result.setCodError(4);
                result.setMensaje("Código de Aplicación o Módulo no válido");
            } else {
                //verificando que el usuario tenga permisos para acceder a la aplicación en cuestión.
                Usuario user = lstUser.get(0);
                Modulo module = lstModulo.get(0);

                List<Zonal> lstZonal = getService().findByNamedQuery("Zonal.findByNidUsuarioNidModuloActivos", new Object[]{user.getId(), module.getId()});
                if (lstZonal.isEmpty()) {
                    result.setCodError(5);
                    result.setMensaje("Usuario no tiene permisos para acceder a la Aplicación o Módulo");
                } else {
                    
                    List<UsuarioPerfil> usuarioPerfilList = getService().findByNamedQuery("UsuarioPerfil.findByNidUsuarioAndFlgActivo", new Object[]{user.getId(), Constante.ESTADO_ACTIVO});
                    /**
                     * Validación de caducidad del perfil
                     */
                    if (validaCaducidaDelPerfil(usuarioPerfilList, gcal.getTime(), module)) {
                        result.setCodError(18);
                        result.setMensaje("El Perfil del Usuario ha caducado, contactese con el administrar del sistema");
                    }else{
                        if (validaHorarioPerfil(usuarioPerfilList, gcal.getTime())) {
                            result.setCodError(19);
                            result.setMensaje("El usuario no se encuentra dentro del horario de acceso permitido");
                            return result;
                        } else {
                            ControlAcceso loginLog = new ControlAcceso();
                            loginLog.setNidUsuario(user);
                            loginLog.setCodZonal(user.getCodZonal());
                            loginLog.setTxtSessionid(null);
                            loginLog.setNidModulo(module);
                            loginLog.setFecRegistro(fechaActual);
                            loginLog.setFlgAcceso(Constante.INTENTO_VALIDO);
                            loginLog.setTipOperacion(Constante.TIPO_OPERACION_INICIO_SESION);

                            loginLog = (ControlAcceso) getService().save(loginLog);

                            //completando el resultado
                            //unidad territorial
                            unidadTerritorial = new UnidadTerritorial[lstZonal.size()];
                            for (int i = 0; i < lstZonal.size(); i++) {
                                unidadTerritorial[i] = new UnidadTerritorial();
                                unidadTerritorial[i].setCodZonal(lstZonal.get(i).getCodZonal());
                                unidadTerritorial[i].setTxtUnidadTerritorial(lstZonal.get(i).getTxtZonal());
                            }
                            //datos del usuario
                            datosUsuario.setCodigoUsuario(user.getCodUsuario());
                            datosUsuario.setNidUsuario(user.getId());
                            datosUsuario.setNombreUsuario(user.getNombreCompleto());
                            datosUsuario.setTipoUsuario(user.getTipUsuario());
                            datosUsuario.setUnidadTerritorial(unidadTerritorial);
                            datosUsuario.setnIdControlAccesoWeb(loginLog.getId());
                            //resultado
                            result.setCodError(0);
                            result.setMensaje("Usuario autenticado satisfactoriamente");
                            result.setDatosUsuario(datosUsuario);
                        }
                    }
                }
            }
        }
        return result;
    }

    public int parseSubErrorCode(String message) {
        Matcher m = SUB_ERROR_CODE.matcher(message);
        if (m.matches()) {
            return Integer.parseInt(m.group(1), 16);
        }
        return -1;
    }

    public void calcularIntentosFallidos(Long nIdUsuario) throws ServiceException {
        List<ControlAcceso> listTmp = null;
        listTmp = getService().findByNamedQuery("ControlAcceso.findByNidUsuarioAndTipOperacion", new Object[]{"%"+Constante.TIPO_OPERACION_INICIO_SESION+"%", nIdUsuario});
        fechaUltIngresoExitoso = ultimoIngreso(listTmp, Constante.INTENTO_VALIDO);
        Date fechUltimoIntentoFallido = fechaUltIngresoExitoso;
        int fails = 0;
        int oks = 0;
        int indiceFinal=(listTmp.size() - 1);
        if(indiceFinal > 20){
            indiceFinal = 20;
        }
        for (int i = 0; i <= (listTmp.size() - 1); i++) {
            if (DateHelper.fechasDiferenciaEnDias(fechaUltIngresoExitoso, listTmp.get(i).getFecRegistro()) <= 0) {
                if (listTmp.get(i).getFlgAcceso().equals(Constante.INTENTO_VALIDO)) {
                    oks++;
                } else {
                    if (listTmp.get(i).getFlgAcceso().equals(Constante.INTENTO_RECHAZADO)) {
                        fails++;
                        if (DateHelper.fechasDiferenciaEnDias(fechUltimoIntentoFallido, listTmp.get(i).getFecRegistro()) <= 0) {
                            fechUltimoIntentoFallido = listTmp.get(i).getFecRegistro();
                            textoCaptchaGuardada = listTmp.get(i).getTxtReferencia();
                        }
                    }
                }
            }
        }
        intentosRechazados = fails;
        intentosValidos =oks;
        ultimoIngreso = fechUltimoIntentoFallido;
    }

    public Date ultimoIngreso(List<ControlAcceso> tempo, String tipoIntento) {
        Date ultimo = Constante.FECHA_INICIO;
        Date fecha_bd;
        String st;

        for (int i = 0; i <= (tempo.size() - 1); i++) {
            fecha_bd = tempo.get(i).getFecRegistro();
            st = tempo.get(i).getFlgAcceso();
            if ((DateHelper.fechasDiferenciaEnDias(ultimo, fecha_bd) <= 0) && st.equals(tipoIntento)) {
                ultimo = fecha_bd;
            }
        }
        return ultimo;
    }

    public OpcionMenu crearMenuOpcion(OpcionMenu opcionPadre, Long idUsuario, String codZonal, String flgConsultaPadre) throws ServiceException {
        List<OpcionMenu> opciones = new ArrayList<OpcionMenu>();
        Map<Long, OpcionMenu> mapa= new HashMap<Long, OpcionMenu>();
        OpcionMenu opcionMenu = null;
        List<Object[]> listaAcciones = getService().findByNamedQuery("Opcion.findOtherLevelNodes", new Object[]{opcionPadre.getNidOpcion(), idUsuario, codZonal});
        for (Object[] obj : listaAcciones) {
            opcionMenu = new OpcionMenu();
            opcionMenu.setNidModulo(opcionPadre.getNidModulo());
            opcionMenu.setTxtModulo(opcionPadre.getTxtModulo());
            opcionMenu.setNidModuloPadre(opcionPadre.getNidModuloPadre());
            opcionMenu.setTxtModuloPadre(opcionPadre.getTxtModuloPadre());
            opcionMenu.setNidOpcion(Long.parseLong(obj[0].toString()));
            opcionMenu.setTxtOpcion(obj[1].toString());
            if (obj[2] != null) {
                opcionMenu.setNidOpcionPadre(Long.parseLong(obj[2].toString()));
            }
            opcionMenu.setNumOrden(Integer.parseInt(obj[3].toString()));
            opcionMenu.setNidAccion(Long.parseLong(obj[4].toString()));
            opcionMenu.setTxtAccion(obj[5].toString());
            if (obj[6] != null) {
                opcionMenu.setTxtNombreObjeto(obj[6].toString());
            }
            if (obj[7] != null) {
                opcionMenu.setTxtUrl(obj[7].toString());
            }
            opcionMenu.setFlgDefault(obj[8].toString());
            
            if(opcionPadre.getFlgPerfilConsulta() != null && opcionPadre.getFlgPerfilConsulta().equals(Constante.FLAG_CONSULTA)){
                opcionMenu.setFlgConsulta(Constante.FLAG_CONSULTA);
            }else{
                if(opcionPadre.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                    opcionMenu.setFlgConsulta(Constante.FLAG_CONSULTA);
                }else{
                    if(flgConsultaPadre.equals(Constante.FLAG_CONSULTA)){
                        opcionMenu.setFlgConsulta(Constante.FLAG_CONSULTA);
                    }else{
                        opcionMenu.setFlgConsulta(obj[9].toString());
                    }
                }
            }
            if (obj[10] != null) {
                opcionMenu.setTxtOpcionNombreObjeto(obj[10].toString());
            }
            if (obj[11] != null) {
                opcionMenu.setFlgVisible(obj[11].toString());
            }
            if(mapa.containsKey(opcionMenu.getNidOpcion())){
                if(mapa.get(opcionMenu.getNidOpcion()).getFlgConsulta().equals(Constante.FLAG_CONSULTA) && !opcionMenu.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                    mapa.put(opcionMenu.getNidOpcion(), opcionMenu);
                }
            }else{
                mapa.put(opcionMenu.getNidOpcion(), opcionMenu);
            }
            //opciones.add(opcionMenu);
        }
        opciones.addAll(mapa.values());
        opcionPadre.setOpciones(opciones.toArray(new OpcionMenu[opciones.size()]));
        for (OpcionMenu opcion : opciones) {
            opcion = crearMenuAccion(opcion, idUsuario, codZonal, flgConsultaPadre);
            opcion = crearMenuOpcion(opcion, idUsuario, codZonal, flgConsultaPadre);
        }
        return opcionPadre;
    }
    public void crearMenu(OpcionMenu opcionPadre, HashMap<OpcionMenu, ArrayList<OpcionMenu>> menuBar, Long idUsuario, String codZonal, String flgConsultaPadre) throws ServiceException {
        List<OpcionMenu> opciones = new ArrayList<OpcionMenu>();
        OpcionMenu opcionMenu = null;
        List<Object[]> listaAcciones = getService().findByNamedQuery("Opcion.findOtherLevelNodes", new Object[]{opcionPadre.getNidOpcion(), idUsuario, codZonal});
        for (Object[] obj : listaAcciones) {
            opcionMenu = new OpcionMenu();
            opcionMenu.setNidModulo(opcionPadre.getNidModulo());
            opcionMenu.setTxtModulo(opcionPadre.getTxtModulo());
            opcionMenu.setNidModuloPadre(opcionPadre.getNidModuloPadre());
            opcionMenu.setTxtModuloPadre(opcionPadre.getTxtModuloPadre());
            opcionMenu.setNidOpcion(Long.parseLong(obj[0].toString()));
            opcionMenu.setTxtOpcion(obj[1].toString());
            if (obj[2] != null) {
                opcionMenu.setNidOpcionPadre(Long.parseLong(obj[2].toString()));
            }
            opcionMenu.setNumOrden(Integer.parseInt(obj[3].toString()));
            opcionMenu.setNidAccion(Long.parseLong(obj[4].toString()));
            opcionMenu.setTxtAccion(obj[5].toString());
            opcionMenu.setTxtNombreObjeto(obj[6].toString());
            if (obj[7] != null) {
                opcionMenu.setTxtUrl(obj[7].toString());
            }
            opcionMenu.setFlgDefault(obj[8].toString());
            if(opcionPadre.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                opcionMenu.setFlgConsulta(Constante.FLAG_CONSULTA);
            }else{
                if(flgConsultaPadre.equals(Constante.FLAG_CONSULTA)){
                    opcionMenu.setFlgConsulta(Constante.FLAG_CONSULTA);
                }else{
                    opcionMenu.setFlgConsulta(obj[9].toString());
                }
            }
            opciones.add(opcionMenu);
        }
        for (OpcionMenu opcion : opciones) {
            if (!menuBar.containsKey(opcion)) {
                opcion = crearMenuAccion(opcion, idUsuario, codZonal, flgConsultaPadre);
                menuBar.get(opcionPadre).add(opcion);
                crearMenu(opcion, menuBar, idUsuario, codZonal, flgConsultaPadre);
            }
        }
    }

    public OpcionMenu crearMenuAccion(OpcionMenu opcionPadre, Long idUsuario, String codZonal, String flgConsultaPadre) throws ServiceException {
        List<AccionMenu> acciones = new ArrayList<AccionMenu>();
        AccionMenu accion = null;
        Accion nIdAccion = null;
        List<Object[]> lista = getService().findByNamedQuery("Accion.findByNidOpcionOtherLevelNodes", new Object[]{opcionPadre.getNidOpcion(), idUsuario});
        Map<Long, AccionMenu> mapa= new HashMap<Long, AccionMenu>();
        for (Object[] obj : lista) {
            nIdAccion =  new Accion();
            nIdAccion = (Accion) obj[0];
            accion = new AccionMenu();
            if(opcionPadre.getFlgPerfilConsulta() != null && opcionPadre.getFlgPerfilConsulta().equals(Constante.FLAG_CONSULTA)){
                accion.setFlgConsulta(Constante.FLAG_CONSULTA);
            }else{
                if(opcionPadre.getFlgConsulta().equals(Constante.FLAG_CONSULTA)){
                    accion.setFlgConsulta(Constante.FLAG_CONSULTA);
                }else{
                    if(flgConsultaPadre.equals(Constante.FLAG_CONSULTA)){
                        accion.setFlgConsulta(Constante.FLAG_CONSULTA);
                    }else{
                        accion.setFlgConsulta(obj[1].toString());
                    }
                }
            }
            accion.setNidAccion(nIdAccion.getId());
            accion.setNidOpcion(opcionPadre.getNidOpcion());
            accion.setTxtAccion(nIdAccion.getTxtAccion());
            accion.setTxtNombreObjeto(nIdAccion.getTxtNombreObjeto());
            if(nIdAccion.getTxtUrl() != null){
                accion.setTxtUrl(nIdAccion.getTxtUrl());
            }
            if (mapa.containsKey(accion.getNidAccion())) {
                if (mapa.get(accion.getNidAccion()).getFlgConsulta().equals(Constante.FLAG_CONSULTA) && !accion.getFlgConsulta().equals(Constante.FLAG_CONSULTA)) {
                    mapa.put(accion.getNidAccion(), accion);
                }
            } else {
                mapa.put(accion.getNidAccion(), accion);
            }
            //acciones.add(accion);
        }
        acciones.addAll(mapa.values());
        opcionPadre.setAcciones(acciones.toArray(new AccionMenu[acciones.size()]));
        return opcionPadre;
    }
    
    public String generarTextoCaptcha() {
        int charsToPrint = 6;
        char[] chars = Constante.ELEGIBLE_CHARS.toCharArray();
        StringBuilder finalString = new StringBuilder();
        for (int i = 0; i < charsToPrint; i++) {
            double randomValue = Math.random();
            int randomIndex = (int) Math.round(randomValue * (chars.length - 1));
            char characterToShow = chars[randomIndex];
            finalString.append(characterToShow);
        }
        return finalString.toString();
    }

    private String retornaPasswordTemporal(String codUsuario, String firsLetterApeMat, String firsLetterApePat, String firsLetterNombre, String tipo, Integer numAleatorio) throws Exception {
        String codUsuarioSinArroba = codUsuario;
        if (codUsuarioSinArroba.lastIndexOf(Constante.CARACTER_USUARIO_DOMINIO) > -1) {
            codUsuarioSinArroba = codUsuarioSinArroba.replace(Constante.CARACTER_USUARIO_DOMINIO + "", "");
        }
        String enc_clave = codUsuarioSinArroba + firsLetterApeMat + firsLetterApePat + firsLetterNombre + numAleatorio;
        log.info("Clave DesEncriptada: " + enc_clave);
        if (tipo.equals("1")) {
            enc_clave = retornaClaveEncriptada(enc_clave, codUsuario);
            log.info("Clave Encriptada: " + enc_clave);
        }
        return enc_clave;
    }

    public String obtenerDireccionIP(){
        InetAddress direccion = null;
        try {
            direccion = InetAddress.getLocalHost();
        } catch (UnknownHostException ex) {
            log.error("ERROR en obtenerDireccionIP :"+ex);
        }
        if(direccion != null){
            return direccion.getHostAddress();
        }else{
            return "";
        }
    }
    
    public GenericService getService() {
        return service;
    }

    public void setService(GenericService service) {
        this.service = service;
    }
    
    @Override
    public CerrarSesionResult CerrarSesion(String codigoUsuario, String nidModulo, String nIdCtrlAccesoWeb) {
        CerrarSesionResult result = new CerrarSesionResult();
        try {
            if (codigoUsuario == null || codigoUsuario.trim().equals("")) {
                result.setCodError(2);
                result.setMensaje("Por favor ingresa tu código de usuario");
                return result;
            }
            if (nidModulo == null || nidModulo.trim().equals("")) {
                result.setCodError(3);
                result.setMensaje("Por favor ingresa el nidModulo");
                return result;
            }
            if (Utilitarios.tieneLetras(nidModulo)) {
                result.setCodError(4);
                result.setMensaje("Módulo no existe");
                return result;
            }
            if (Utilitarios.tieneLetras(nIdCtrlAccesoWeb)) {
                result.setCodError(5);
                result.setMensaje("Control de Acceso no existe");
                return result;
            }
            List<ControlAcceso> lstControl = getService().findByNamedQuery("ControlAcceso.findById", new Object[]{new Long(nIdCtrlAccesoWeb)});
            if (lstControl.isEmpty()) {
                result.setCodError(6);
                result.setMensaje("Control de Acceso no registrado");
            } else {
                GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
                ControlAcceso control = lstControl.get(0);
                control.setFecSalida(gcal.getTime());
                getService().save(control);
                //resultado
                result.setCodError(0);
                result.setMensaje("Cierre de Sesion satisfactorio");
            }
        } catch (Exception e) {
            log.error(String.format("Método %s : %s", "CerrarSesion", e));
            result.setCodError(1);
            result.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return result;
    }
    
    public boolean validaCaducidadClave(String flgCaducidad, Date fechaActual, Date fecCambioClave){
        boolean bValidaCadClave = false;
        if(flgCaducidad.equals(Constante.CLAVE_CADUCADA)){
            if(fecCambioClave != null){
                if (fecCambioClave.before(fechaActual)) {
                    bValidaCadClave = true;
                }
            }
        }
        return bValidaCadClave;
    }
    
    public boolean validaCaducidaDelPerfil(List<UsuarioPerfil> usuarioPerfilList, Date fechaActual, Modulo nidModulo){
        boolean bValidaCaducidad = false;
        try {
            for (UsuarioPerfil up : usuarioPerfilList) {
                if(up.getNidPerfil().getNidModulo().getId().equals(nidModulo.getId())){
                    if(up.getFecInicio() != null && up.getFecFin() != null){
                        if (up.getFecInicio().before(fechaActual) && up.getFecFin().before(fechaActual)) {
                            up.setFlgCaduca(Constante.PERFILUSUARIO_CADUCADA);
                            getService().save(up);
                            bValidaCaducidad = true;
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("ERROR en validaCaducidaDelPerfil: "+e);
        }
        return bValidaCaducidad;
    }
    
    public boolean validaHorarioPerfil(List<UsuarioPerfil> usuarioPerfilList, Date fechaActual){
        boolean bvalidaHorario = false;
        try {
            List<Long> idsUsuarioPerfilList = new ArrayList<Long>();
            List<HorarioPerfil> horarioPerfil = null;
            for (UsuarioPerfil up : usuarioPerfilList) {
                if(up.getFlgHorarioRestringido().equals(Constante.ESTADO_ACTIVO)){
                    idsUsuarioPerfilList.add(up.getId());
                }
            }
            if(!idsUsuarioPerfilList.isEmpty()){
                horarioPerfil = getService().findByNamedQuery("HorarioPerfil.findByNIdUsuarioPerfil", new Object[]{idsUsuarioPerfilList, Constante.ESTADO_ACTIVO});
            }else{
                horarioPerfil = new ArrayList<HorarioPerfil>();
            }            
            if (!horarioPerfil.isEmpty()) {//before = antes
                for (HorarioPerfil hp : horarioPerfil) {
                    if (hp.getFecHoraInicio().before(fechaActual) && hp.getFecHoraFin().after(fechaActual)) {
                        bvalidaHorario = true;
                        break;
                    }
                }
            }
        } catch (ServiceException ex) {
            log.error("ERROR en validaHorarioPerfil: "+ex);
        }
        return bvalidaHorario;
    }

    @Override
    public ObtenerParametrosResult obtenerParametrosGenerales(String sDominio) throws Exception {
        ObtenerParametrosResult result = new ObtenerParametrosResult();
        try {
            if (sDominio == null || sDominio.trim().equals("")) {
                result.setCodError(2);
                result.setMensaje("Por favor ingresa tu dominio");
                return result;
            }
            List<General> lstGeneral = getService().findByNamedQuery("General.findByTxtDominioWS", new Object[]{sDominio});
            if (lstGeneral.isEmpty()) {
                result.setCodError(3);
                result.setMensaje("Dominio no existe");
                return result;
            }
            lstGeneral = getService().findByNamedQuery("General.findByTxtDominioEstado", new Object[]{sDominio, Constante.ESTADO_ACTIVO});
            ParametroGeneral[] parametroGeneral = new ParametroGeneral[lstGeneral.size()];
            for (int i = 0; i < lstGeneral.size(); i++) {
                parametroGeneral[i] = new ParametroGeneral();
                parametroGeneral[i].setIdParametro(lstGeneral.get(i).getId());
                parametroGeneral[i].setDescripcionParametro(lstGeneral.get(i).getTxtParametro());
                parametroGeneral[i].setValorParametro(lstGeneral.get(i).getTxtValor());
            }
            result.setCodError(0);
            result.setMensaje("Se devolvió el listado de los parametros satisfactoriamente");
            result.setParametros(parametroGeneral);
        } catch (Exception e) {
            log.error(String.format("Método %s : %s", "obtenerParametrosGenerales", e));
            result.setCodError(1);
            result.setMensaje("Ocurrió un error inesperado, por favor comuníquese con el administrador");
        }
        return result;
    }
}